package com.project.frba.bi.queueing;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.SqlProvider;

import com.project.frba.bi.descriptor.Descriptor;
import com.project.frba.bi.descriptor.Dimension;
import com.project.frba.bi.descriptor.Property;
import com.project.frba.bifront.client.model.Filter;

public class OlapQueryBuilder implements PreparedStatementCreator, SqlProvider{
	
	private Descriptor descriptor;
	
	public OlapQueryBuilder(Descriptor descriptor){
		this.descriptor = descriptor;
	}
	
	public String getCubeQuery(List<String> properties, List<Filter> filters){
		String query = getSelect(properties) + getFrom() + 
					getJoins(properties) + getWhere(filters) + getGroupBy(properties) + " " + getOrderBy(properties);
		System.out.println(query);
		return query.toLowerCase();
		
	}
	
	public String getSelect(List<String> properties){
		StringBuffer selectBuffer = new StringBuffer("SELECT sum(f.metric) as metric"); 
		for (String propertyName : properties) {
			selectBuffer.append(", ");
			selectBuffer.append(this.descriptor.getPropertyByName(propertyName).getOlapAbsolutePath());
		}
		
		return selectBuffer.toString();
	}
	
	public String getFrom(){
		return " FROM " + descriptor.getDescriptorName() + "facttable_" + this.descriptor.getFacttable() + " f ";
	}
	
	public String getJoins(List<String> properties){
		List<String> dimensionsVisited = new ArrayList<String>();
		StringBuffer joinsBuffer = new StringBuffer();
		for (String propertyName : properties) {
			Property property = this.descriptor.getPropertyByName(propertyName);
			Dimension dimension = property.getDimension();
			if(!dimensionsVisited.contains(dimension.getName())){
				joinsBuffer.append("INNER JOIN " + this.descriptor.getDescriptorName().toLowerCase() + dimension.getName() +  "dimension " + 
						dimension.getOlapAliasTable() + " ON f." + dimension.getName() + "dimension = " + dimension.getOlapAliasTable() + ".id ");
				dimensionsVisited.add(dimension.getName());
			} 
		}
		
		return joinsBuffer.toString();
	}
	
	public String getGroupBy(List<String> properties){
		StringBuffer groupByBuffer = new StringBuffer("GROUP BY ");
		for (String propertyName : properties) {
			Property property = this.descriptor.getPropertyByName(propertyName);
			groupByBuffer.append(property.getOlapAbsolutePath() + ", ");
		}
		
		return groupByBuffer.substring(0, groupByBuffer.length() - 2);
	}
	
	public String getOrderBy(List<String> properties){
		StringBuffer groupByBuffer = new StringBuffer("ORDER BY ");
		for (String propertyName : properties) {
			Property property = this.descriptor.getPropertyByName(propertyName);
			groupByBuffer.append(property.getOlapAbsolutePath() + ", ");
		}
		
		return groupByBuffer.substring(0, groupByBuffer.length() - 2);
	}
	
	public String getWhere(List<Filter> filters){
		if(filters.size() == 0){
			return "";
		}
		
		StringBuffer whereBuffer = new StringBuffer("WHERE ");
		for (Filter filter : filters) {
			whereBuffer.append("(");
			Property property = this.descriptor.getPropertyByName(filter.getPropertyName());
			for (String filterValue : filter.getFilterValues()) {
				whereBuffer.append(property.getOlapAbsolutePath() + " = '" + filterValue + "' or ");				
			}
			whereBuffer.append(" 1=0) and ");
		}
		whereBuffer.append("1=1 ");
		
		return whereBuffer.toString();
	}
	
	public String getAllPropertyValues(String propertyName){
		Property property = descriptor.getPropertyByName(propertyName);
		Dimension dimension = property.getDimension();
		StringBuffer buff = new StringBuffer("SELECT DISTINCT ");
		buff.append(property.getOlapAbsolutePath());
		buff.append(" FROM " + dimension.getOlapAbsolutePath() + ";");
		
		return buff.toString();
	}
	
	public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}
	
	public String getSql() {
		return null;
	}

}
